#include <assert.h>
#include <ctype.h>
#include <locale.h>
#include <errno.h>
#include <float.h>
#include <inttypes.h>
#include <limits.h>
#include <math.h>
#include <pthread.h>
#include <setjmp.h>
#include <signal.h>
#include <stdarg.h>
#include <stddef.h>
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <stdnoreturn.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
#include<windows.h>

void simple_assertion(void)
{
    printf("***** simple_assertion *****\n");
    /* Uncomment to disable `assert()` */
    // #define NDEBUG

    int x = -1;
    // assert(x>=0); // exit compile , I don't know why it exit.

    printf("x = %d\n", x);
}


/*
A static assertion is one that is checked at compile time, not run time. 
The condition must be a constant expression, and if false will result in a compiler error. 

The first argument, the condition that is checked, must be a constant expression, and the second a string literal.
Unlike assert, _Static_assert is a keyword.
A convenience macro static_assert is defined in <assert.h>.
*/
void static_assertion(void)
{
    printf("***** static_assertion *****\n");
    enum { N = 5 };
    _Static_assert(N == 5, "N does not equal 5");
    // static_assert(N>10, "N is not greater than 10"); /* compiler error */

}


void assert_error_messages(void)
{
    printf("***** assert_error_messages *****\n");
    int* p;
    /*
    If the assertion failed, an error message would resemble
    Assertion failed: p != NULL, file main.c, line 5
    */
    assert( p != NULL );
    /*
    However, you can use logical AND (&&) to give an error message as well
    Assertion failed: p != NULL && "function f: p cannot be NULL", file main.c, line 5
    */
    assert( p != NULL && "p cannot be NULL");
}


int precondition_postcondition(int* a, int count)
{
    printf("***** precondition_postcondition *****\n");
    int i, result = 0;
    /* Precondition: */
    /* NULL is an invalid vector */
    assert (a != NULL);
    /* Number of dimensions can not be negative.*/
    assert (count >= 0);
    /* Calculation */
    for (i = 0; i < count; ++i)
    {
    result = result + (a[i] * a[i]);
    }
    /* Postcondition: */
    /* Resulting length can not be negative. */
    assert (result >= 0);
    return result;
}

void main(void)
{
    // simple_assertion();

    // static_assertion();

    // assert_error_messages();

    #define COUNT 3
    int a[COUNT] = {1, 2, 3};
    int *b = NULL;
    int r;
    r = precondition_postcondition (a, COUNT);
    printf ("r = %i\n", r);
    system("pause");
    r = precondition_postcondition (b, COUNT);
    printf ("r = %i\n", r);
    system("pause");
}